package fem3d;

import java.util.ArrayList;

import fem2.AbstractStructuralStaticDemo;
import fem2.Constraint;
import fem2.Element;
import fem2.Force;
import fem2.GravityLoad;
import fem2.Load;
import fem2.MaterialModel;
import fem2.Mesh;
import fem2.MeshGenerator;
import fem2.MeshPart;
import fem2.MeshUtilities;
import fem2.Model;
import fem2.Node;
import fem2.analysis.Analysis;
import fem2.analysis.NonlinearStaticAnalysis;
import fem2.element.StructuralElement;
import fem2.enu.EchoLevelType;
import fem2.enu.State;
import fem2.material.FluencyCriteria;
import fem2.material.LinearIsotropicHardeningRule;
import fem2.material.LinearKinematicHardeningRule;
import fem2.material.VonMisesMM;
import fem2.observer.StressObserver;
import fem2.pre_and_post.GidMeshGenerator;

public class Beam3dVonMises extends AbstractStructuralStaticDemo {

	String fn;

	public Beam3dVonMises() {
		projectDir = "/home/hbui/kratos_janosch";
		projectName = "beam3d.gid";
		fn = projectDir + '/' + projectName + '/' + "mesh2.msh";
	}

	@Override
	public Mesh createMesh() {
		MeshGenerator mg = new GidMeshGenerator(fn);
		return mg.getMesh(3);
	}

	@Override
	public Model createConditions(Model m) {
		Mesh mesh = m.getMesh();
		/*
		 * boundary conditions
		 */
		Constraint c1 = new Constraint(false, false, false);
		ArrayList<Node> side = MeshUtilities.seekNodesOnSurface(mesh, 0.0, 1.0, 0.0, 0.0);
		mesh.setConstraint(c1, side);

		/*
		 * load
		 */
		double F = -0.1 * 10e6;
		Node n1 = MeshUtilities.seekNode(mesh, 0.0, 12.0, 0.0);
		Node n2 = MeshUtilities.seekNode(mesh, 1.0, 12.0, 0.0);
		Force f1 = new Force(n1, 0.0, 0.0, F);
		Force f2 = new Force(n2, 0.0, 0.0, F);
		m.addLoad(f1);
		m.addLoad(f2);

		/*
		 * gravity
		 */
		double rho = 7850;
		// double g = -9.81;
		// FunctionRnToR f = new ConstantFunctionRnToR(rho * g);
		for (int i = 0; i < m.getMesh().countBlocks(); i++) {
			// Load l = new DistributedLoad(mesh.getBlock(i), null, f, null);
			Load l = new GravityLoad(mesh.getBlock(i), rho);
			m.addLoad(l);
		}

		return m;
	}

	@Override
	public MaterialModel createMaterial(Model m) {
		double E = 25850 * 10e6;
		double nu = 0.18;
		double ft = 2.7 * 10e6;
		double H = E / 2;
		double K = E / 2;
		FluencyCriteria isoLaw = new LinearIsotropicHardeningRule(ft, K);
		FluencyCriteria kinLaw = new LinearKinematicHardeningRule(H);
		return new VonMisesMM(E, nu, 1.0, 0, State.THREE_DIMENSIONAL, isoLaw, kinLaw);
	}

	@Override
	public Element createElement(MeshPart mp, MaterialModel mm) {
		return new StructuralElement(mp, mm);
	}

	@Override
	public void run(int nt) {
		Model m = createModel();

		Analysis an = new NonlinearStaticAnalysis(m, nt);
		an.getStrategy().addObserver(new StressObserver(m));
		an.getStrategy().setEchoLevel(EchoLevelType.OUTPUT, EchoLevelType.AUX1);
		an.run();

		postProcess(m);
	}

	public static void main(String[] args) {
		Beam3dVonMises demo = new Beam3dVonMises();

		demo.run(10);
	}
}
